#pragma once

#include <functional>

namespace test
{
	//void add_test_function(const char * funcName, 

	namespace detail
	{
		struct TestInitializer
		{
		public:
			TestInitializer(const char * funName, std::function<void ()> fn);
		};

		class TestException : public std::exception
		{
		public:
			TestException() {}
			TestException(const char * msg) : std::exception(msg) {}
		};
	}

	bool run_all_tests();
}

#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __LINE__)

#define TEST_F(fn)\
	static void fn();\
	static ::test::detail::TestInitializer MAKE_UNIQUE(_testInitializer_)(#fn, fn);\
	static void fn()


#define ASSERT_TRUE(exp)	if( !(exp) ) { throw ::test::detail::TestException(#exp " is false" ); }
#define ASSERT_EQ(value, exp)	if( (value) != (exp) ) { throw ::test::detail::TestException(#value " is not " #exp); }
